//ITCClient.java

package com.ibm.tspaces.contrib.ITC;


/*
**  Licensed Materials - Property of IBM
**
**  (C) COPYRIGHT IBM Corp. 1996, 1997, 1998  All rights reserved
**
**  US Government Users Restricted Rights - Use, duplication or
**  disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
**
**/

import java.util.*;
import java.awt.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import com.ibm.tspaces.*;


/*
************************************************************************
** ITCClient **
***************
*/
/**
** ITCClient is the client interface to the Internet T Space Chat (ITC)
** ITC requires that an instance of ITCServer be running in the same
** T Space.
** @see
** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
** @author Kevin Eustice <kevin@cs.hmc.edu>
************************************************************************
*/


public class ITCClient extends Frame
{
  //static vars

  private static String    _spaceName  = "ITC";    //our TSpacename
  private static String    _serverName = "tspaces";//our server
  private static String    _userName        = ""; //who we are
  private static String    _passWord        = ""; // our password for
                                                  //return validation
  private static String    _channel         = ""; //Which channel are you in?
  private static boolean   _connected = false;    // are we connected
  private static com.ibm.tspaces.TupleSpace  _ts   = null;  // our T Space


  boolean fComponentsAdjusted = false;

  java.awt.FileDialog openFileDialog1;
  static java.awt.TextField textField1;
  static java.awt.TextArea textArea;
  java.awt.MenuBar mainMenuBar;
  java.awt.Menu menu1;
  java.awt.MenuItem menuItem1;
  java.awt.MenuItem miExit;
  java.awt.Menu menu2;
  java.awt.MenuItem miCut;
  java.awt.MenuItem miCopy;
  java.awt.MenuItem miPaste;
  java.awt.Menu menu3;
  java.awt.MenuItem miAbout;

  /*
  ***************************************************************************
  ** ITCClient ** (constructor)
  ***************
  */
  /**
  ** The constructor creates the main Frame and sets up the layout.
  ** We add two TextFields, one non-editable (viewing area), and one editable
  ** (for user input).
  **
  ** @param none
  ** @return
  ** @exception
  ***************************************************************************
  */

  /** Default Constructor
  **
  **
  */
public ITCClient()
  {
    setLayout(null);
    setVisible(false);
    //Hardcoded size for now -- this may be changed later to allow
    //arbitrary resizing
    setSize(getInsets().left + getInsets().right + 634,
	    getInsets().top + getInsets().bottom + 427);
    textArea = new java.awt.TextArea("Welcome to Internet T Space Chat v1.0\n"+
			       "Written by Kevin Eustice <kevin@cs.hmc.edu>\n"
				     ,30,80,TextArea.SCROLLBARS_VERTICAL_ONLY);
    textArea.setBounds(getInsets().left + 0,getInsets().top + 0,634,368);
    textArea.setEditable(false);
    add(textArea);
    textField1 = new java.awt.TextField();
    textField1.setBounds(getInsets().left + 0,getInsets().top + 368,634,60);
    textField1.addActionListener(new ActionListener ()
				 {
                                   public void actionPerformed(ActionEvent e) {
				    String input = textField1.getText().trim();
				    parse(input);
				    textField1.setText("");
				   } // end actionPerformed
				 }); // end ActionListener
    add(textField1);

    setTitle("Internet T Space Chat -- " + _userName + "@" + _channel);

    // Setup our menus
    mainMenuBar = new java.awt.MenuBar();
    menu1 = new java.awt.Menu("ITC");
    miExit = new java.awt.MenuItem("Exit");
    menu1.add(miExit);
    mainMenuBar.add(menu1);
    menu3 = new java.awt.Menu("Help");
    mainMenuBar.setHelpMenu(menu3);
    miAbout = new java.awt.MenuItem("About..");
    menu3.add(miAbout);
    mainMenuBar.add(menu3);
    setMenuBar(mainMenuBar);
    SymWindow aSymWindow = new SymWindow();
    this.addWindowListener(aSymWindow);
    SymAction lSymAction = new SymAction();
    miAbout.addActionListener(lSymAction);
    miExit.addActionListener(lSymAction);
    textField1.setEditable(false);
  } // end constructor




  /*
  ***************************************************************************
  ** login **
  ***********
  */
  /**
  ** login() pops up a dialog the prompts the user for login name and
  ** password, and then attempts to login to the T Space.  If the user name
  ** is already in use, we call ourselves again.
  **
  ** @param none
  ** @return
  ** @exception
  ***************************************************************************
  */




public static void login()
  {
    Frame f = new Frame("ITC Login");
    String[] prompts = new String[] {"Userid:   " , "Password:"};
    String[] defaults = new String[] {"",""};
    PWDialog me = new PWDialog(f,"ITC Login",prompts,defaults);
    me.setEchoChar(1,'*');      //don't echo back characters, return '*'s
    me.setVisible(true);        //Hocus pocus, let the invisible become visible
    String[] results = me.getResults();
    _userName = results[0];
    _passWord = results[1];
    //retry until we get a valid username
    if(!TSConnect()) login();
  } // end login

  /*
  ***************************************************************************
  ** parse **
  ***********
  */
  /**
  ** parse() takes an input String and parses it.
  ** Valid / prefixed commands are executed, invalid commands ignored.
  ** Non / prefixed input will be interpreted as a message to the channel.
  ** @param String input
  ** @return
  ** @exception
  ***************************************************************************
  */

  //parse strings for system commands
  public void parse(String input_)
  {
    StringTokenizer token = new StringTokenizer(input_, "/ ", true);
    //our delimiters are /'s and spaces.
    //we want the delimiters returned as tokens
    if(input_.length()==0) return; //empty string?  bad input.
    String tmp = token.nextToken();
    tmp = tmp.toLowerCase();
    String newname = "";

    if(!tmp.equals("/")) { //Okay, we said something in the channel
      try {
	_ts.write(new Tuple("ITCIN",_userName, _channel, _userName + ": "
			    + input_ + "\n"));
      } catch (Exception yae) {
	System.err.println("An exception occurred.");
      } // end catch

    }  // end if

    else {  // parse command
      tmp = token.nextToken().toLowerCase();
      if(tmp.equals("nick")) {  //requested nick change
	String oldname = _userName;

	try {
	    newname = token.nextToken();
	    while(newname.equals(" ")) newname = token.nextToken();
	} catch (NoSuchElementException nsee)
	  {
	    textArea.append("!!!You must specify a username!!!\n");
	    return;
	  }  // end catch

        try {
	  _ts.write(new Tuple("ITCIN",oldname,"NICKCHG", newname));
	  //submit the nick change to the Server
	  //wait for result
	  Tuple result = _ts.waitToTake(
					new Tuple("ITCCMD",oldname,"NICKCHG",
					Field.makeField("java.lang.String")));
	  String condition = (String) result.getField(3).value();
	  if(condition.equals("SUCC")) {  //it worked
	    textArea.append("Nick change succeeded.\n");
	    _userName = newname;
	    setTitle("Internet T Space Chat -- " + _userName + "@" + _channel);
	    return;
	  }  //end if
	  else if(condition.equals("FAIL"))
	    {  //whoops!  nick change failed
	      textArea.append("Nick change failed.\n");
	    }  // end else if
	} catch (Exception e)
	  {
	    System.err.println("Exception in T Space operations.");
	  } // end catch;

      } // end if
      else if(tmp.equals("join")) {  // channel join
	String oldchannel = _channel;
	_channel = token.nextToken();
	while(_channel.equals(" ")) _channel = token.nextToken();
	if(_channel.equals("LIST") || _channel.equals("JOIN")
	   || _channel.equals("WHO") || _channel.equals("NICKCHG")) {

	  textArea.append("Bad channelname.\n");
	  // don't let users pick command words as channel names
	  _channel = oldchannel;
	  return;
	} // end if

	setTitle("Internet T Space Chat -- " + _userName + "@" + _channel);
	try {
	  _ts.write(new Tuple("ITCIN",_userName,"JOIN",_channel));
	  _ts.write(new Tuple("ITCIN",_userName, "WHO",""));
	} catch (Exception e)
	  {
	  System.err.println("Error in accessing T Space.");
	  }; // end catch

      } //end join else if
      else if(tmp.equals("list")) {
	try {
	  _ts.write(new Tuple("ITCIN",_userName, "LIST",""));
	} catch (Exception e)
	  {
	    System.err.println("Error in accessing T Space.");
	  }; //end catch
      }  //end list else if

      else if(tmp.equals("who")) {
	try {
	  _ts.write(new Tuple("ITCIN",_userName, "WHO",_channel));
	} catch (Exception e)
	  {
	    System.err.println("Error in accessing T Space.");
	  };  //end catch

      } //end who else if
      else if(tmp.equals("msg")) {
        String recip = "";
	String msg = "";
	try {
	  recip = token.nextToken();
	  while(recip.equals(" ")) recip = token.nextToken();
	  while(token.hasMoreTokens())
	    msg = new String(msg + token.nextToken());
	} catch (NoSuchElementException nsee2)
	  {
	    textArea.append("/msg <name> <msg>\n");
	    return;
	  } //end catch
	try{
	  //submit message to T Space
	  _ts.write(new Tuple("ITCOUT",recip, "MSG",
			      "< Message from "+_userName + " > " +
			      msg + "\n"));
	} catch (Exception e)
	  {
	    System.err.println("Error in accessing T Space.");
	  };
      }//end msg else if
    } // end else not equals "/"
  } //end parse


  /*
  ***************************************************************************
  ** TextListener **
  ******************
  */
  /**
  ** TextListener watched the T Space for Tuples addressed
  ** to the local user.
  ** @param none
  ** @return none
  ** @exception
  ***************************************************************************
  */



public void TextListener() {
  System.out.println("Starting text listener.");
  while(true) {
    try {
      Thread.sleep(300);
    } catch (Exception te)
      {
	System.err.println("Exception accessing Thread");
      };
    if(_connected)
      {
	try {
	  //Get incoming Tuples addressed to us.
	  //Maybe we need ids to contain session info, maybe IP?
	  //as is -- output can be split between multiple sessions

	  Tuple result = _ts.waitToTake(new Tuple("ITCOUT",_userName,
				        Field.makeField("java.lang.String"),
				        Field.makeField("java.lang.String")));

	  textArea.append((String) result.getField(3).value());
	} catch (Exception ie) {
	System.err.println("Exception in waitToTake()");
	} //end catch
      } //end if
  } //end while
} //end TextListener


  /*
  ***************************************************************************
  ** addNotify **
  ***************
  */
  /**
  ** addNotify calls the addNotify method from the super class
  ** and creates the component's native peer.
  ** we then resize taking insets into account and translate the
  ** components accordingly.
  ** @param none
  ** @return none
  ** @exception
  ***************************************************************************
  */

  //component notifier
public void addNotify()
  {
    Dimension d = getSize();

    super.addNotify(); //this call is crucial -- create the component peer

    if (fComponentsAdjusted)
      return;

    setSize(getInsets().left + getInsets().right + d.width,
	    getInsets().top + getInsets().bottom + d.height);

    Component components[] = getComponents();

    for (int i = 0; i < components.length; i++) {
      Point p = components[i].getLocation();
      p.translate(getInsets().left, getInsets().top);
      components[i].setLocation(p);
    } //end for
    fComponentsAdjusted = true;
  } // end addNotify




/*
************************************************************************
** SymWindow **
***************
*/
/**
** SymWindow is an inner class that handles the window shutting down
**
** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
** @author Kevin Eustice <kevin@cs.hmc.edu>
************************************************************************
*/


class SymWindow extends java.awt.event.WindowAdapter
{
  public void windowClosing(java.awt.event.WindowEvent event)
  {
    Object object = event.getSource();
    if (object == ITCClient.this) {
      setVisible(false);//hide();		 // hide the Frame
      dispose();	  // free the system resources
      System.exit(0); // close the application
    }
  }
}

 /*
  ***************************************************************************
  ** ITCClient_WindowClosing **
  *****************************
  */
  /**
  ** Bring the window down, right now.
  ** @param WindowEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */

  public void ITCClient_WindowClosing(java.awt.event.WindowEvent event)
  {
	  this.setVisible(false);//hide();		 // hide the Frame
	  dispose();	  // free the system resources
	  System.exit(0); // close the application
  }
  /*
  ************************************************************************
  ** SymAction **
  ***************
  */
  /**
  ** SymAction is an inner class that does event handling
  **
  ** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
  ** @author Kevin Eustice <kevin@cs.hmc.edu>
  ************************************************************************
  */

  class SymAction implements java.awt.event.ActionListener
  {
	  public void actionPerformed(java.awt.event.ActionEvent event)
	  {
		  Object object = event.getSource();
		  if (object == miAbout)
			  miAbout_Action(event);
		  else if (object == miExit)
			  miExit_Action(event);

	  }
  }


 /*
  ***************************************************************************
  ** miAbout_Action **
  ********************
  */
  /**
  ** Create an about dialog
  ** @param ActionEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */
  void miAbout_Action(java.awt.event.ActionEvent event)
  {
	  (new AboutDialog(this, true)).show();

  }

  /*
  ***************************************************************************
  ** miExit_Action **
  ********************
  */
  /**
  ** Create an Exit dialog
  ** @param ActionEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */
  void miExit_Action(java.awt.event.ActionEvent event)
  {
	  (new QuitDialog(this, true)).show();
  }


  /*
  ***************************************************************************
  ** TSConnect **
  ***************
  */
  /**
  ** Try to create the T Space, and login to it.
  ** @param ActionEvent event
  ** @return true if connected
  ** @exception
  ***************************************************************************
  */
  static boolean TSConnect()
  {
    try {
      _ts = new TupleSpace(_spaceName, _serverName); }

    catch (Exception e)
      {
	System.err.println("Exception.");
      }; // end catch

    try {
      //write out the user creation tuple
      _ts.write(new Tuple("ITCIN",_userName,"NEWUSER", _passWord));
      _channel = "#Lobby";
      //set our initial location to #Lobby
      //wait for  the user creation result tuple
      Tuple result = _ts.waitToTake(
		     new Tuple("ITCCMD",_userName,"CREATE",
			       Field.makeField("java.lang.String")));

      _ts.delete(result);
      //get the value
      String condition = (String) result.getField(3).value();
      if(condition.equals("SUCC"))
	{ //we succeeded
	  textArea.append("Connection succeeded.\n");
	  _connected = true;
	  textField1.setEditable(true);
	  return true;
	} //end if

      else { //whoops....failed to login.
	  textArea.append("Connection failed - nick in use.\n");
	  return false;
      } // end else

    }
    catch (Exception e)
      {
	System.err.println("Exception writing to T Space.");
      }; //end catch
    return false;
  } //end TSConnect

  /*
  ***************************************************************************
  ** main **
  **********
  */
  /**
  ** Create a new ITCClient, login and create a TextListener
  ** @param String[] args -- args[0] should be the servername
  ** @return nothing
  ** @exception
  ***************************************************************************
  */
static public void main(String args[])
  {
    try {
      if( args.length != 0 ){
	_serverName = args[0]; //get our servername from command line
      }
    } catch (Exception e) {
      System.out.println(e.getMessage());
      e.printStackTrace();
    }  //end catch

    ITCClient itc = new ITCClient(); //new Client
    itc.setVisible(true); //let's take a look at it.
    login();  // login
    itc.TextListener(); //Set up a listener
  } //end main
}// end ITCClient





/*
************************************************************************
** QuitDialog **
****************
*/
/**
** QuitDialog is a class that generates a dialog box and handles exiting
**
** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
** @author Kevin Eustice <kevin@cs.hmc.edu>
************************************************************************
*/


class QuitDialog extends Dialog
{

  //class variables

  boolean fComponentsAdjusted = false;
  java.awt.Button yesButton;
  java.awt.Button noButton;
  java.awt.Label label1;


  /*
  ***************************************************************************
  ** QuitDialog **
  ****************
  */
  /**
  ** The constructor creates a dialog box and sets up buttons
  ** It takes the parent frame, and a boolean value to specify modality
  ** @param none
  ** @return
  ** @exception
  ***************************************************************************
  */
  public QuitDialog(Frame parent, boolean modal)
  {
    super(parent, modal);
    setLayout(null);
    setSize(getInsets().left + getInsets().right + 337,
	    getInsets().top + getInsets().bottom + 135);
    //yes button
    yesButton = new java.awt.Button(" Yes ");
    yesButton.setBounds(getInsets().left + 72,getInsets().top + 80,79,22);
    yesButton.setFont(new Font("Dialog", Font.BOLD, 12));
    add(yesButton);
    // no button
    noButton = new java.awt.Button("  No  ");
    noButton.setBounds(getInsets().left + 185,getInsets().top + 80,79,22);
    noButton.setFont(new Font("Dialog", Font.BOLD, 12));
    add(noButton);
    // Quit? label
    label1 = new java.awt.Label("Do you really want to quit?",Label.CENTER);
    label1.setBounds(78,33,180,23);
    add(label1);
    setTitle("Internet T Space Chat - Quit");
    setResizable(false);
    SymWindow aSymWindow = new SymWindow();
    this.addWindowListener(aSymWindow);
    SymAction lSymAction = new SymAction();
    noButton.addActionListener(lSymAction);
    yesButton.addActionListener(lSymAction);
  } //end constructor

 /*
  ***************************************************************************
  ** addNotify **
  ***************
  */
  /**
  ** addNotify calls the addNotify method from the super class
  ** and creates the component's native peer.
  ** we then resize taking insets into account and translate the
  ** components accordingly.
  ** @param none
  ** @return none
  ** @exception
  ***************************************************************************
  */

public void addNotify()
  {
    Dimension d = getSize();

    super.addNotify();

    if (fComponentsAdjusted)
      return;


    setSize(getInsets().left + getInsets().right + d.width,
	    getInsets().top + getInsets().bottom + d.height);
    Component components[] = getComponents();
    for (int i = 0; i < components.length; i++)
      {
	Point p = components[i].getLocation();
	p.translate(getInsets().left, getInsets().top);
	components[i].setLocation(p);
      } //end for
    fComponentsAdjusted = true;
  } //end addNotify


 /*
  ***************************************************************************
  ** setVisible **
  ****************
  */
  /**
  ** setVisible toggles the visibility of the dialog
  ** @param boolean true or false?
  ** @return none
  ** @exception
  ***************************************************************************
  */
public synchronized void setVisible(boolean b)
  {
      if (b) {
	    Rectangle bounds = getParent().getBounds();
	    Rectangle abounds = getBounds();

	    setLocation(bounds.x + (bounds.width - abounds.width)/ 2,
			bounds.y + (bounds.height - abounds.height)/2);
      }
      super.setVisible(b);
  } //end setVisible

  /*
  ************************************************************************
  ** SymWindow **
  ***************
  */
  /**
  ** SymWindow is an inner class that handles the closing of the window
  **
  ** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
  ** @author Kevin Eustice <kevin@cs.hmc.edu>
  ************************************************************************
  */

  class SymWindow extends java.awt.event.WindowAdapter
  {
   public void windowClosing(java.awt.event.WindowEvent event)
    {
      Object object = event.getSource();
      if (object == QuitDialog.this)
	QuitDialog_WindowClosing(event);
    }
  } //end SymWindow

 /*
  ***************************************************************************
  ** QuitDialog_WindowClosing **
  ******************************
  */
  /**
  ** Bring the window down, right now.
  ** @param WindowEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */
  void QuitDialog_WindowClosing(java.awt.event.WindowEvent event)
  {
    dispose();
  } //end QuitDialog_WindowClosing

  /*
  ************************************************************************
  ** SymAction **
  ***************
  */
  /**
  ** SymAction is an inner class that does event handling
  **
  ** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
  ** @author Kevin Eustice <kevin@cs.hmc.edu>
  ************************************************************************
  */

  class SymAction implements java.awt.event.ActionListener
  {
   public void actionPerformed(java.awt.event.ActionEvent event)
    {
      Object object = event.getSource();
      if (object == noButton)
	noButton_Clicked(event);
      else if (object == yesButton)
	yesButton_Clicked(event);
    } //end actionPerformed
  } //end SymAction


 /*
  ***************************************************************************
  ** yesButton_Clicked **
  ***********************
  */
  /**
  ** Handles the yes button event
  ** @param ActionEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */


  void yesButton_Clicked(java.awt.event.ActionEvent event)
  {
    Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new WindowEvent((java.awt.Window)getParent(), WindowEvent.WINDOW_CLOSING));
  }
  /*
  ***************************************************************************
  ** noButton_Clicked **
  **********************
  */
  /**
  ** Handles the no button event
  ** @param ActionEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */

  void noButton_Clicked(java.awt.event.ActionEvent event)
  {
    dispose();
  }

}


/*
************************************************************************
** AboutDialog **
*****************
*/
/**
** AboutDialog is a class that generates a dialog box and handles exiting
**
** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
** @author Kevin Eustice <kevin@cs.hmc.edu>
************************************************************************
*/

class AboutDialog extends Dialog {

  java.awt.TextArea label1;
  java.awt.Button okButton;
  boolean fComponentsAdjusted = false;


  /*
  ***************************************************************************
  ** AboutDialog **
  *****************
  */
  /**
  ** The constructor creates a dialog box and sets up the button/textfield
  ** It takes the parent frame, and a boolean value to specify modality
  ** @param Frame, boolean
  ** @return
  ** @exception
  ***************************************************************************
  */

  public AboutDialog(Frame parent, boolean modal)
  {
	  super(parent, modal);

	  setLayout(null);
	  setSize(400,400);
	  label1 = new java.awt.TextArea(
		 "Internet T Space Chat\nWritten by Kevin Eustice\n"
		 +" Here's a list of Commands for ITC:\n"
		 +" '/list' for a list of valid channels.\n"
		 +" '/join <channelname>' to join or create a channel.\n"
		 +" '/nick <nickname>' to change your alias.\n"
		 +" '/msg <username> msg' to whisper a message to username.\n"
		 +" '/who' for a list of users in a channel.\n",
		 340,380,TextArea.SCROLLBARS_NONE);
	  //stick the help here too....
	  label1.setBounds(20,20,360,300);
	  add(label1);
	  okButton = new java.awt.Button("OK");
	  okButton.setBounds(95,350,66,27);
	  add(okButton);
	  setTitle("About");
	  setResizable(false);
	  SymWindow aSymWindow = new SymWindow();
	  this.addWindowListener(aSymWindow);
	  SymAction lSymAction = new SymAction();
	  okButton.addActionListener(lSymAction);

  } //end constructor


 /*
  ***************************************************************************
  ** addNotify **
  ***************
  */
  /**
  ** addNotify calls the addNotify method from the super class
  ** and creates the component's native peer.
  ** we then resize taking insets into account and translate the
  ** components accordingly.
  ** @param none
  ** @return none
  ** @exception
  ***************************************************************************
  */

  public void addNotify()
  {
    Dimension d = getSize();
    super.addNotify();
    if (fComponentsAdjusted)
      return;
    setSize(getInsets().left + getInsets().right + getSize().width,
	    getInsets().top + getInsets().bottom + getSize().height);
    Component components[] = getComponents();
    for (int i = 0; i < components.length; i++)
      {
	Point p = components[i].getLocation();
	p.translate(getInsets().left, getInsets().top);
	components[i].setLocation(p);
      } //end for
    fComponentsAdjusted = true;
  } // end addNotify

 /*
  ***************************************************************************
  ** setVisible **
  ****************
  */
  /**
  ** setVisible toggles the visibility of the dialog
  ** @param boolean true or false?
  ** @return none
  ** @exception
  ***************************************************************************
  */

  public synchronized void setVisible(boolean b)
  {
      if (b) {
	    Rectangle bounds = getParent().getBounds();
	    Rectangle abounds = getBounds();

	    setLocation(bounds.x + (bounds.width - abounds.width)/ 2,
		     bounds.y + (bounds.height - abounds.height)/2);
  }

	  super.setVisible(b);
  }


  /*
  ************************************************************************
  ** SymWindow **
  ***************
  */
  /**
  ** SymWindow is an inner class that handles the closing of the window
  **
  ** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
  ** @author Kevin Eustice <kevin@cs.hmc.edu>
  ************************************************************************
  */

  class SymWindow extends java.awt.event.WindowAdapter
  {
	  public void windowClosing(java.awt.event.WindowEvent event)
	  {
		  Object object = event.getSource();
		  if (object == AboutDialog.this)
			  AboutDialog_WindowClosing(event);
	  }
  }


 /*
  ***************************************************************************
  ** AboutDialog_WindowClosing **
  *******************************
  */
  /**
  ** Bring the window down, right now.
  ** @param WindowEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */
  void AboutDialog_WindowClosing(java.awt.event.WindowEvent event)
  {
	  dispose();
  } //end AboutDialog_WindowClosing

 /*
  ************************************************************************
  ** SymAction **
  ***************
  */
  /**
  ** SymAction is an inner class that does event handling
  **
  ** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
  ** @author Kevin Eustice <kevin@cs.hmc.edu>
  ************************************************************************
  */

  class SymAction implements java.awt.event.ActionListener
  {
	  public void actionPerformed(java.awt.event.ActionEvent event)
	  {
		  Object object = event.getSource();
		  if (object == okButton)
			  okButton_Clicked(event);
	  } //end actionPerformed
  } //end SymAction


 /*
  ***************************************************************************
  ** okButton_Clicked **
  **********************
  */
  /**
  ** Handles the ok button event
  ** @param ActionEvent event
  ** @return none
  ** @exception
  ***************************************************************************
  */

  void okButton_Clicked(java.awt.event.ActionEvent event)
  {
	  dispose();

  } //end okButtonClicked

} //end AboutDialog classs



/*
************************************************************************
** PWDialog **
**************
*/
/**
** PWDialog is a dialog class that allows the echo char to be changed
** this is a *very* slight modification of com.ibm.almaden.gcs.HGRequestDialog
**
** @version $Revision: 2.1 $ $Date: 1999/11/05 22:22:37 $
************************************************************************
*/

class PWDialog extends Dialog {
  //class vars
private String[] 		_Results;
private TextField[]		_TFResults;
private	int			_Length=10;       // Default TextField length
protected boolean		_Cancel=false;

  /*
  ************************************************************************
  ** PWDialog **
  **************
  */
  /**
  ** Constructor that will request a single String.
  **
  ** @param Parent Frame for Dialog.
  ** @param Title for the Dialog box
  ** @param Prompt for the TextField.
  ** @param Default value.  Use enpty string if no default.
  **
  */
public
PWDialog(Component parent, String title, String prompt, String defaulted )
  {
    this(parent,title,new String[] {prompt}, new String[] {defaulted} );
  }

  /*
  ************************************************************************
  ** PWDialog **
  **************
  */
  /**
  ** Constructor that will request a two or more Strings.
  **
  ** @param Parent Frame for Dialog.
  ** @param Title for the Dialog box
  ** @param array of Prompts for the TextField.
  ** @param array of Default values.  Use enpty string if no default.
  **
  ************************************************************************
  */

  public
  PWDialog( Component parent, String title, String[] prompts, String[] defaults)
  {
    super( getFrame(parent), title, true );
    Panel outerpanel = new Panel();
    outerpanel.setLayout(new BorderLayout());

    Panel centerPanel = new Panel();
    int rows = prompts.length;
    _Results = new String[rows];
    _TFResults = new TextField[rows];
    for (int i=0; i < rows; i++)
      _Length = Math.max(_Length,defaults[i].length());
    centerPanel.setLayout(new GridLayout(rows,1));
    for (int i=0; i < rows; i++)
      {
	Panel p = setupPrompt(i,prompts[i],defaults[i]);
	centerPanel.add(p);
      }
    outerpanel.add("Center", centerPanel);
    this.add("Center",outerpanel);
    Panel p2 = new Panel();
    Button ok = new Button("OK");
    ok.addActionListener(
			 new ActionListener()
			 {
                          public void actionPerformed(ActionEvent evt)
			    {
			      dispose();
			    } // end actionPerformed
			 } ); //end ActionListener

    p2.add(ok);
    Button cancel = new Button("Cancel");
    cancel.addActionListener(
			     new ActionListener()
			     {
                              public void actionPerformed(ActionEvent evt) {
				PWDialog.this._Cancel = true;
				dispose();
			      } //end actionPerformed
			     } ); //end ActionListener

    p2.add(cancel);

    this.add("South", p2);

    pack();
    Dimension size = this.getSize();
    this.setSize(size.width+30,size.height+10);

  }  //end constructor

 /*
  ************************************************************************
  ** setEchoChar **
  *****************
  */
  /**
  ** This will set the specified field so that the user input is suppressed.
  **
  ** @param element to be suppressed.
  ** @param char to be used to suppress the input.
  ************************************************************************
  */

public void
setEchoChar(int element,char c)  {

  _TFResults[element].setEchoChar(c);

}


  /*
  ************************************************************************
  ** getResults **
  ****************
  */
  /**
  ** Obtain an array of result strings.
  ** It will return "null" when the user presses Cancel
  ************************************************************************
  */
public String[]
getResults() {
  if (_Cancel)
    return null;

  for (int i=0; i<_TFResults.length; i++)
    _Results[i] = _TFResults[i].getText();

  return _Results;
}
  /*
  ************************************************************************
  ** setupPrompt **
  *****************
  */
  /**
  ** Setup the user prompts
  ** @param int which element
  ** @param String the Prompt
  ** @param String default value
  ** @return Panel the created panel
  ************************************************************************
  */

  private Panel
  setupPrompt(int element, String prompt, String defaulted) {
    Panel panel = new Panel();
    Label labelPrompt = new Label(prompt);


    _TFResults[element] = new TextField(defaulted,_Length);


   final int num = element;
    _TFResults[element].addActionListener(
      new ActionListener() {
	public void actionPerformed(ActionEvent evt) {
	  TextField tf = (TextField)evt.getSource();
	  String result = tf.getText();

	  // Now do the same thing as if the user pressed OK
	  dispose();
	}
      } );

    panel.add(labelPrompt);
    panel.add(_TFResults[element]);
    return panel;
  }


  /*
  ************************************************************************
  ** getFrame **
  *****************
  */
  /**
  ** Gets the parent frame from an Applet
  ** @paraem Component the parent component
  ** @return the parent Frame
  ************************************************************************
  */
  private static Frame
  getFrame(Component c) {

    Component parent = c;

    while ( ! (parent instanceof Frame) )
	  parent = parent.getParent();

    return (Frame)parent;
  }




}


/* $Log: ITCClient.java,v $
/* Revision 2.1  1999/11/05 22:22:37  estesp
/* Update revision number to 2.1 on all files
/*
/* Revision 1.1.1.1  1999/11/05 16:24:52  estesp
/* Imported 2.1.0 release into Austin CVS
/*
 * Revision 1.2  1999/06/17 05:39:36  thodes
 *   Updated the inital checkin to append the "Log" field and
 * convert CR/LF to CR (for win/unix interop).
 *
 *   The inital checkin lower-cased directrory names, and omitted
 * many dirs/files that will added later, e.g., MoDAL stuff.
 *
 * All of the above will need to be done to all VSS-to-CVS
 * converted sources.  In summary, in moving from VSS to CVS, do this:
 *  - lower-case dir names
 *  - CR/LF --> CR
 *  - append CVS "Log" entties
 *
 * (a script that helps with #2 and #3 is in
 *     tspaces1:~thodes/bin/update-keywords.sh)
 * 
 */


